package com.good.shopping.product.redis;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.good.shopping.product.entity.CategoryEntity;
import com.good.shopping.product.vo.Catelog2Vo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 1.缓存 - 本地缓存使用
 *   加锁 解决本地 - 只查询一次数据库，其他请求走缓存
 * @author shengren.yan
 * @create 2022-02-23
 */
public class redis1 {

    // redis
    @Autowired
    StringRedisTemplate redisTemplate;

    public Map<String, List<Catelog2Vo>> getCatalogJson() {

        // 给缓存中放json字符串，拿出json字符串，还要逆转为能用的对象类型【序列化与反序列化】
        // 1、加入缓存逻辑  catalogJSON 缓存数据
        String catalogJSON = redisTemplate.opsForValue().get("catalogJSON");
        if (StringUtils.isEmpty(catalogJSON)){

            System.out.println("缓存没有命中----------，将要查询数据库");

            //2、缓存中没有，查询数据库
            Map<String, List<Catelog2Vo>> catelogJsonFromDB = getCatalogJsonFromDb();

            //3、将查到的数据再放入缓存，将对象转为JSON在缓存中
            // 对象转成JSON
            String jsonString = JSON.toJSONString(catelogJsonFromDB);
            redisTemplate.opsForValue().set("catalogJSON",jsonString,1, TimeUnit.DAYS);
            return catelogJsonFromDB;
        }

        System.out.println("缓存命中---------");
        // JSON字符串转对象
        Map<String, List<Catelog2Vo>> result =
                JSON.parseObject(catalogJSON,new TypeReference<Map<String, List<Catelog2Vo>>>(){});

        return result;
    }

    // 优化三级分类 - 只查询数据库里的数据
    private synchronized Map<String, List<Catelog2Vo>> getCatalogJsonFromDb() {

        // 本地 + 加锁 可以解决 只有一条线程查询数据库，其他线程都是走缓存
        synchronized(this){

            // 双重检测锁
            // 得到锁之后，还需要去缓存中查询一下，双重检测锁
            String catalogJSON = redisTemplate.opsForValue().get("catalogJSON");
            if (!StringUtils.isEmpty(catalogJSON)){
                Map<String, List<Catelog2Vo>> result =
                        JSON.parseObject(catalogJSON,new TypeReference<Map<String, List<Catelog2Vo>>>(){});
                return result;
            }

            // 只查询一次数据库 - 其他的都走缓存
            System.out.println("查询了数据库 -----"+ Thread.currentThread().getName());

            // 查询全部  只查询一次数据库  模拟 执行SQL 语句查询
            Map<String, List<Catelog2Vo>> parent_cid = null;

            // 3 查到的数据放入缓存，将对象转为json放在缓存中  有效期为1天
            String jsonString = JSON.toJSONString(parent_cid);
            redisTemplate.opsForValue().set("catalogJSON",jsonString,1,TimeUnit.DAYS);
            return parent_cid;

        }

    }

}
